/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package ejercicio.practica7;

import static java.lang.Math.pow;
import static java.lang.Math.sin;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

/**
 *
 * @author manolo
 */
public class piParaleloFutureCont implements Callable {

    private double radio = 1.0;
    private int umbral;
    private int cuenta = 0;

    public piParaleloFutureCont(int umbral) {
        this.umbral = umbral;
    }

    @Override
    public Integer call() throws Exception {

        for (int i = 0; i < umbral; i++) {
            double xCoord = Math.random()* radio;
            double yCoord = Math.random() * radio;
            if ((pow(xCoord, 2) + pow(yCoord, 2)) <= pow(radio, 2)) {
                cuenta++;
            }
        }
        return cuenta;
    }

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        int lanzados = 0;
        float pi = 0;
        int numProcesadores = Runtime.getRuntime().availableProcessors();
        double Cb = 0.5;
        int numHilos = (int) (numProcesadores / (1 - Cb));
        double inicio, fin;
        Scanner teclado = new Scanner(System.in);

        System.out.println("Estimación del número Pi usando el método Montecarlo: ");
        System.out.println("Inserte el numero de puntos: ");
        lanzados = teclado.nextInt();
        int umbral = lanzados / numHilos;
        Integer resultado = 0;
        ArrayList<Future<Integer>> future = new ArrayList<>();
        inicio = System.nanoTime();
        Thread[] hilo = new Thread[numHilos];
        for (int i = 0; i < numHilos; i++) {
            //Creamos las instancias necesarias
            Callable<Integer> contador = new piParaleloFutureCont(umbral);

            //creaamos los objetos de las tareas
            FutureTask<Integer> tarea = new FutureTask<Integer>(contador);
            //Añadimos al ArraList
            future.add(tarea);

            //Creamos el hilo
            hilo[i] = new Thread(tarea);

            //iniciamos el hilo
            hilo[i].start();

        }

        // Extraemos los valores del arrayList donde se han almacenado los resultados
        for (int i = 0; i < numHilos; i++) {
            resultado += future.get(i).get();
        }

        fin = System.nanoTime();
        pi = 4 * ((float) resultado / lanzados);

        System.out.println("La estimación es: " + pi);
        System.out.println("Operación realizada en " + (fin - inicio) / 1E6 + " mseg.");
    }
}
